<template>
  <div class="components-video" :class="classList" ref="container">
    <video controls muted class="default-video" v-if="!status.play" disablepictureinpicture></video>
    <div class="icon-bar" v-if="status.play">
      <el-icon class="full-icon" title="全屏" @click.stop="fullPlayer">
        <FullScreen />
      </el-icon>
      <el-icon class="close-icon" title="关闭" @click.stop="destroyPlayer">
        <CloseBold />
      </el-icon>
    </div>
    <div class="plugin-container" ref="player" v-if="status.init"></div>
  </div>
</template>

<script setup>
import { CloseBold, FullScreen } from '@element-plus/icons-vue'
import { ref, onUnmounted, reactive, nextTick } from "vue"

const emit = defineEmits(['close', 'error'])
let flv = null
const classList = ref([])
const player = ref()
const status = reactive({ focus: false, tag: "", id: '', play: false, loading: false, init: false })
const container = ref()
const timer = ref()

// 关闭播放器
function destroyPlayer() {
  emit("close", status.id, status.tag)
  status.id = ""
  status.tag = ""
  status.play = false
  status.loading = false
  flv?.destroy()
  flv = null
}

// 播放器全屏
const fullPlayer = () => {
  player.value?.requestFullscreen()
}

// 聚焦
const doFocus = () => {
  classList.value = ['focus']
  status.focus = true
}

// 失焦
const doBlur = () => {
  classList.value = ['blur']
  status.focus = false
}

// 提醒用户
const warn = () => {
  const dom = container.value
  if (dom) {
    const keyframes = [{ transform: 'translateY(5px)' }, { transform: 'translateY(10px)' }, { transform: 'translateY(0px)' }]
    const options = { duration: 300, iterations: 1, easing: 'ease-in-out' }
    const animations = dom.getAnimations()
    animations.forEach(animation => animation.cancel())
    dom.animate(keyframes, options)
  }
}

// 开始播放
async function play(id, tag, src) {
  destroyPlayer()
  status.init = true
  await nextTick()
  status.id = id
  status.tag = tag
  status.loading = true
  startPlayer(src)
}

function startPlayer(src) {
  // 检查 Jessibuca 是否可用
  if (!window.Jessibuca) {
    emit("error", "播放器未加载，请刷新页面重试")
    return
  }

  try {
    flv = new window.Jessibuca({
      container: player.value,
      videoBuffer: 0.3,
      decoder: "/dist/decoder.js",
      loadingText: "加载中",
      hasAudio: false,
      isResize: false,
      useMSE: false,  // 关闭MSE，使用WebGL渲染
      hiddenAutoPause: true,
      autoWasm: true,
      loadingTimeoutReplay: false,
      forceNoOffscreen: true,
      isNotMute: true,
      useOffscreen: false,  // 关闭离屏渲染
      debug: false,  // 关闭调试模式
    })

    flv.on("loadingTimeout", async () => {
      emit("error", "加载视频超时,已停止播放")
      await nextTick()
      destroyPlayer()
    })

    flv.on("timeout", function () {
      // 连接超时处理
    })

    flv.on("delayTimeout", function () {
      // 延迟超时处理
    })

    flv.on("start", async () => {
      status.play = true
      status.loading = false
    })

    flv.on("error", (error) => {
      emit("error", "播放错误: " + (error.message || error))
    })

    flv.play(src)

    // 3分钟后重连
    timer.value = setTimeout(() => {
      clearTimeout(timer.value)
      if (flv) {
        flv.destroy()
        startPlayer(src)
      }
    }, 1000 * 60 * 3)
  } catch (error) {
    emit("error", "创建播放器失败: " + (error.message || error))
  }
}

defineExpose({ play, status, warn, doFocus, doBlur })

onUnmounted(() => {
  clearTimeout(timer.value)
  flv?.destroy()
})
</script>

<style lang="scss" scoped>
@use '@/styles/variables.scss' as *;

.components-video {
  border: 3px solid transparent;
  position: relative;

  &.focus {
    border-color: var(--danger-color);
  }

  &.blur {
    border-color: transparent;
  }

  .default-video {
    position: absolute;
    width: 100%;
    height: 100%;
    object-fit: fill;
    z-index: 1;
    background-color: var(--background-color-darker);
    pointer-events: none;
  }

  .icon-bar {
    position: absolute;
    top: var(--spacing-sm);
    right: var(--spacing-sm);
    z-index: 3;

    .el-icon {
      cursor: pointer;
      margin-right: var(--spacing-sm);
      color: var(--color-white);
    }

    .close-icon {
      font-size: var(--font-size-xl);
    }

    .full-icon {
      font-size: var(--font-size-lg);
    }
  }

  .plugin-container {
    z-index: 2;
    width: 100%;
    height: 100%;
  }
}
</style>
